// 引入必要的命名空间
using Microsoft.EntityFrameworkCore; // 提供Entity Framework Core功能
using UniversalAdmin.Application.DTOs; // 引入数据传输对象定义
using UniversalAdmin.Domain.Entities;
using UniversalAdmin.Infrastructure.Data.Contexts; // 引入数据库上下文

namespace UniversalAdmin.Application.Services;

// 用户服务类，实现IUserService接口
public class UserService : IUserService
{
    // 数据库上下文实例
    private readonly ApplicationDbContext _db;

    // 构造函数，注入数据库上下文
    public UserService(ApplicationDbContext db)
    {
        _db = db; // 初始化数据库上下文
    }
    //分页
    public async Task<PagedResultDto<UserDto>> GetUsersAsync(int page, int pageSize)
    {
        var total = await _db.Users.CountAsync();
        var items = await _db.Users
            .OrderBy(u => u.Id)
            .Skip((page - 1) * pageSize)
            .Take(pageSize)
            .Select(u => new UserDto(u.Id, u.Username, u.Email ?? "", u.PhoneNumber, new List<RoleDto>()))
            .ToListAsync();

        return new PagedResultDto<UserDto>
        {
            Items = items,
            TotalCount = total,
            Page = page,
            PageSize = pageSize
        };
    }

    // 根据用户ID获取用户信息
    public async Task<UserDto?> GetUserByIdAsync(Guid id)
    {
        // 异步查询数据库中匹配ID的用户，包含角色信息
        var user = await _db.Users
            .Include(u => u.Roles)
            .FirstOrDefaultAsync(u => u.Id == id);
        if (user == null)
            throw new Exception("用户不存在"); // 用户不存在时抛出异常

        // 返回用户数据传输对象
        return new UserDto(
            user.Id,
            user.Username, // 用户名
            user.Email ?? "",    // 用户邮箱
            user.PhoneNumber, // 用户电话号码
            user.Roles.Select(r => new RoleDto(r.Id, r.Name ?? "", r.Description)).ToList() // 角色信息
        );
    }

    // 根据关键字搜索用户
    public async Task<List<UserDto>> SearchUsersAsync(string keyword)
    {
        // 检查关键字是否为空或空白
        if (string.IsNullOrWhiteSpace(keyword))
            throw new Exception("关键字不能为空"); // 抛出异常

        // 异步查询数据库中匹配关键字的用户（用户名或邮箱模糊匹配）
        var user = await _db.Users
        .Where(u => EF.Functions.Like(u.Username, $"%{keyword}%") // 用户名模糊匹配
        || EF.Functions.Like(u.Email, $"%{keyword}%")) // 邮箱模糊匹配
        .Take(20) // 限制返回结果数量为20
        .ToListAsync(); // 转换为列表

        // 将查询结果转换为UserDto列表
        return user.Select(u => new UserDto(
            u.Id,
            u.Username, // 用户名
            u.Email ?? "",    // 用户邮箱
            u.PhoneNumber, // 用户电话号码
            new List<RoleDto>() // 角色信息（搜索时不包含角色）
        )).ToList();
    }

    // 更新用户信息
    public async Task<UserDto?> UpdateUserAsync(Guid id, UPdateUserDto dto)
    {
        // 查询数据库中匹配ID的用户
        var user = _db.Users.FirstOrDefault(u => u.Id == id);
        if (user == null)
            throw new Exception("用户不存在"); // 用户不存在时抛出异常

        // 更新用户信息
        user.Username = dto.Username; // 更新用户名
        user.Email = dto.Email;      // 更新用户邮箱
        user.PhoneNumber = dto.PhoneNumber; // 更新用户电话号码

        // 保存更改到数据库
        await _db.SaveChangesAsync();

        // 返回更新后的用户数据传输对象
        return new UserDto(
            user.Id,
            user.Username, // 用户名
            user.Email,    // 用户邮箱
            user.PhoneNumber, // 用户电话号码
            new List<RoleDto>() // 角色信息（更新时不包含角色）
        );
    }

    // 创建用户
    public async Task<UserDto> CreateUserAsync(CreateUserDto dto)
    {
        // 检查用户名是否已存在
        if (await _db.Users.AnyAsync(u => u.Username == dto.Username))
            throw new Exception("用户名已存在");

        // 检查邮箱是否已存在
        if (await _db.Users.AnyAsync(u => u.Email == dto.Email))
            throw new Exception("邮箱已存在");

        // 创建新用户
        var user = new User
        {
            Id = Guid.NewGuid(),
            Username = dto.Username,
            Email = dto.Email,
            PhoneNumber = dto.PhoneNumber,
            PasswordHash = BCrypt.Net.BCrypt.HashPassword(dto.Password) // 使用BCrypt加密密码
        };

        // 添加到数据库
        _db.Users.Add(user);
        await _db.SaveChangesAsync();

        // 返回创建的用户数据传输对象
        return new UserDto(
            user.Id,
            user.Username,
            user.Email ?? "",
            user.PhoneNumber,
            new List<RoleDto>()
        );
    }

    // 删除用户
    public async Task<bool> DeleteUserAsync(Guid id)
    {
        // 查询数据库中匹配ID的用户
        var user = await _db.Users.FirstOrDefaultAsync(u => u.Id == id);
        if (user == null)
            return false; // 用户不存在

        // 从数据库中删除用户
        _db.Users.Remove(user);
        await _db.SaveChangesAsync();

        return true; // 删除成功
    }

    // 获取用户的角色列表
    public async Task<IEnumerable<RoleDto>> GetUserRolesAsync(Guid userId)
    {
        var user = await _db.Users
            .Include(u => u.Roles)
            .FirstOrDefaultAsync(u => u.Id == userId);

        if (user == null)
            throw new KeyNotFoundException("用户不存在");

        return user.Roles.Select(r => new RoleDto(r.Id, r.Name ?? "", r.Description));
    }

    // 为用户分配角色
    public async Task AssignRolesToUserAsync(Guid userId, List<Guid> roleIds)
    {
        // 验证用户是否存在
        var user = await _db.Users
            .Include(u => u.Roles)
            .FirstOrDefaultAsync(u => u.Id == userId);

        if (user == null)
            throw new KeyNotFoundException("用户不存在");

        // 验证角色是否都存在
        if (roleIds != null && roleIds.Any())
        {
            var validRoleIds = await _db.Roles
                .Where(r => roleIds.Contains(r.Id))
                .Select(r => r.Id)
                .ToListAsync();

            if (validRoleIds.Count != roleIds.Count)
                throw new KeyNotFoundException("部分角色不存在");
        }

        // 清除用户现有的角色
        user.Roles.Clear();

        // 添加新角色
        if (roleIds != null && roleIds.Any())
        {
            var rolesToAdd = await _db.Roles
                .Where(r => roleIds.Contains(r.Id))
                .ToListAsync();

            foreach (var role in rolesToAdd)
            {
                user.Roles.Add(role);
            }
        }

        await _db.SaveChangesAsync();
    }

    // 获取用户的所有权限
    public async Task<IEnumerable<PermissionDto>> GetUserPermissionsAsync(Guid userId)
    {
        var permissions = await _db.Users
            .Where(u => u.Id == userId)
            .SelectMany(u => u.Roles)
            .SelectMany(r => r.RolePermissions)
            .Select(rp => rp.Permission)
            .Where(p => p != null && p.IsEnabled)
            .Distinct()
            .ToListAsync();

        return permissions.Select(p => new PermissionDto(
            p!.Id,
            p!.Name,
            p!.Description,
            p!.Resource,
            p!.Action,
            p!.Type,
            p!.SortOrder,
            p!.IsEnabled
        ));
    }
}